package main.java.creatures.herbivorous;

import java.awt.Color;
import java.awt.geom.Point2D;
import java.util.Random;

import main.java.creatures.AbstractCreatureEcoSystem;
import main.java.creatures.FactoryCreatures;
import main.java.creatures.IAround;
import main.java.creatures.plant.SimplePlant;
import main.java.creatures.seed.ISeed;
import creatures.ICreature;
import creatures.IEnvironment;

/**
 * 
 * The class SimpleHerbivore represent a simple Herbivorous
 * {@link AbstractCreatureEcoSystem
 *
 */
public class SimpleHerbivore extends AbstractCreatureEcoSystem {

	/**
	 * Represent the max number of herbivorous arround
	 */
	protected int NB_CREATURES_AROUND = 5;
	/**
	 * Herbivorous have eating probability
	 */
	protected int EATING_PROBABILITY = 80;
	/**
	 * Herbivorous have escape probability
	 */
	protected int ESCAPE_PROBABILITY = 70;
	/**
	 * Herbivorous have birth probability
	 */
	protected int BIRTH_EFFISCIENCY = 1;
	/**
	 * Herbivorous have drop probability
	 */
	protected int SEED_DROP_PROBABILITY = 1;

	/**
	 * Herbivorous have a probability to take a seed from a plant
	 */
	protected int TAKE_SEED_PROBABILITY = 60;
	
	/**
	 * Base of probability
	 */
	protected int  PROBABILITY_BASE=100;

	/**
	 * speed average 
	 * {@link #act()}
	 */
	protected double avgSpeed;
	
	/**
	 * direction average
	 * {@link #act()}
	 */
	protected double avgDir;
	
	/**
	 * 
	 */
	protected double minDist;

	/**
	 * Represent life expectancy
	 */
	protected int LIFE_INDICE = 2;

	/**
	 * Define the plante which most close {@link SimplePlant}
	 */
	private SimplePlant plante;

	/**
	 * Current number of Herbivore
	 */
	protected int count = 1;
	/** Minimal speed in pixels per loop. */
	private static final double MIN_SPEED = 3d;

	protected Random rand = new Random();
	
	protected int MIN_HERBIVORE_TO_DELIVER=1;

	public SimpleHerbivore(IEnvironment environment, Point2D position,
			double direction, double speed, Color color) {
		super(environment, position);
		this.direction = direction;
		this.speed = speed;
		this.color = color;
	}

	@Override
	public void isVisitedBy(final SimpleHerbivore h) {
		h.visit(this);

	}

	@Override
	public void isVisitedBy(final SimplePlant p) {
		 p.visit(this);
	}

	@Override
	public void visit(final SimpleHerbivore h) {
		this.avgSpeed += h.getSpeed();
		this.avgDir += h.getDirection();
		this.minDist = Math.min(minDist, h.distanceFromAPoint(getPosition()));
		this.count++;
	}

	@Override
	public void visit(final SimplePlant p) {
		if (this.plante != null
				&& this.distanceFromAPoint(p.getPosition()) < this
						.distanceFromAPoint(this.plante.getPosition())) {
			this.plante = p;
		} else {
			this.plante = p;
		}
	}

	@Override
	public void act() {

		count = 1;
		this.plante = null;
		this.avgDir = direction;
		this.avgSpeed = speed;
		this.minDist = Double.MAX_VALUE;
		for (ICreature c : creaturesAround(this)) {
			((IAround) c).isVisitedBy(this);
		}

		tryToDropSeed();

		boolean eating = (this.plante != null && (rand.nextInt(PROBABILITY_BASE) < EATING_PROBABILITY));
		if (eating) {
			plante.decreaseLife();
			if ((rand.nextInt(PROBABILITY_BASE) < TAKE_SEED_PROBABILITY)) {
				try {
					ISeed seed;
					if ((seed = plante.getSeed()) != null) {
						this.listSeed.add(seed);
					}

				} catch (IllegalStateException e) {
					//la graine est perdu
					System.out
							.println("SimpleHerbivore.act() , Herbivore Full Capacity of Seed");
				}
			}
			tryToDeliver();
		} else {
			this.direction = avgDir / count;
			this.speed = avgSpeed / count;
			if (avgSpeed < MIN_SPEED) {
				avgSpeed = MIN_SPEED;
			}

			if (count > NB_CREATURES_AROUND
					&& rand.nextInt(PROBABILITY_BASE) < ESCAPE_PROBABILITY) {
				setDirection(this.direction + Math.PI / 4);
			}
			// we move always the maximum
			double incX = speed * Math.cos(direction);
			double incY = -speed * Math.sin(direction);
			// we should not moved closer than a dist - MIN_DIST
			move(incX, incY);

			life -= LIFE_INDICE;
		}
		verifyLife();
	}

	/**
	 * Herbovirous could drop seed during the simulation
	 * {@link #SEED_DROP_PROBABLY}
	 * 
	 */
	private void tryToDropSeed() {
		if (rand.nextInt(PROBABILITY_BASE) < this.SEED_DROP_PROBABILITY
				&& this.listSeed.size() != 0) {
			FactoryCreatures.instance.createPlant(this);
			this.listSeed.poll();
		}

	}

	/**
	 * Herbovirous could drop during the simulation {@link #BIRTH_EFFISCIENCY}
	 */
	private void tryToDeliver() {
		if (rand.nextInt(PROBABILITY_BASE) < BIRTH_EFFISCIENCY && this.count > MIN_HERBIVORE_TO_DELIVER) {
			FactoryCreatures.instance.createHerbivorous(this);
		}
	}
}